/*
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *
 *  Authors:
 *  	Albert Marieges Garcia
 *  	Álex Pardo Fernández
 *  	Enric Mayas Márquez
 *  	Juan Carlos Calvo Tejedor
 *  	Marc Gironés Dezsényi
 *  
 *  Contact:
 *  	bcn.tours.android@gmail.com
 *  Webpage:
 *  	bcntours.co.cc
 *
 */

package com.BCNTours.AR.Vista;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;

import com.BCNTours.R;
import com.BCNTours.AR.Utils.Coordinates;

/**
 * Class which draws the points of interest on the screen, showing related info about that point.
 */
public class POIButton extends View{

	//Attributes
	private int id;						//Identification
	private String name;				//Name of the interest point
	private Coordinates coord;			//Coordinate of the interest point
	@SuppressWarnings("unused")
	private float altitude;				//Altitude - Magassag
	float bearing;						
	private Bitmap image;				//Image of the interest point
	private Bitmap background;
	private boolean inScreen;			//Determine whether it should draw on the screen
	private Point p;
	private float distance;				//Distance between the actual location and the interest point
	private float height ;				//Display height
	private float width ;				//Display width
	private String unit;				//Length unit
	
	private float toDisplay;
	@SuppressWarnings("unused")
	private float toDisplay2;
	private float angle;
	private float oldAzimuth;	
	
	/**
	 * Constructor of the class
	 * @param context
	 */
	public POIButton(Context context) {
		super(context);
		// TODO Auto-generated constructor stub
	}
	
	/**
	 * Constructor of the class
	 * @param context
	 * @param params an  arraylist Object, which contains the parameters of the points of interest, 
	 * 				beeing the first one the id of the point of interest, the second its longitude,
	 * 				the third its altitude and the fourth its image id.
	 */
	public POIButton(Context context, ArrayList<Object> params){ 
		super(context);
		id = (Integer) params.get(0);
		coord = (Coordinates) params.get(1);
		altitude = (Float) params.get(2);
		image = BitmapFactory.decodeResource(getResources(), (Integer) params.get(3)) ; //Creates a bitmap from the image id (params[3])
		height = (Float) params.get(4);
		width = (Float) params.get(5);
		name = (String) params.get(6);
		p = new Point(50, 100);
		
	}

	@Override
	protected void onDraw(Canvas canvas) {
		Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL); 
        paint.setColor(Color.WHITE);
//        canvas.drawText(Float.toString(toDisplay), 100,  100 , paint);
        background = BitmapFactory.decodeResource(getResources(), R.drawable.ar_bitmap);
        background.setDensity(canvas.getDensity());
        //Draw the interest point on the screen
		if(inScreen){		
			canvas.drawBitmap(background, p.x,p.y, null);
			canvas.drawBitmap(image, p.x+2, p.y+7 ,null);
			
			paint.setColor(Color.WHITE);
			if(canvas.getDensity() == DisplayMetrics.DENSITY_MEDIUM){
				paint.setTextSize(paint.getTextSize() + 3);
			}else if(canvas.getDensity() == DisplayMetrics.DENSITY_HIGH){
				paint.setTextSize(paint.getTextSize() + 6);
			}
			canvas.drawText(cutText(name), (p.x+(width/8)),  (p.y + (height/19)),paint );
	        canvas.drawText(Double.toString((Math.rint(distance*100)/100)) + unit, (p.x+(width/10)+(width/24)),  (p.y + (height/6)), paint);
		}
		// TODO Auto-generated method stub
		super.onDraw(canvas);
	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		// TODO Auto-generated method stub
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
	}
	
	/**
	 * If the text would be too long to be show onscreen, it would shorten it and add "..." to it.
	 * @param mText The text to check
	 * @return The cut text
	 */
	public String cutText(String mText){
		   if(mText.length() <= 12){
			   return mText;
		   } else{  
			mText = (String) mText.subSequence(0, 9);
			return mText.concat("...");
		   }
	   }
	
	/**
	 * Updates the coordinates of the button.
	 * @param c keep the actual location
	 * @param azimuth Angle between the magnetic north direction and the Y axis, around the Z axis (0 to 359).
	 * @param inclination Rotation around X axis (-180 to 180)
	 * @param lenghtUnit Type of length unit
	 */
	public void updateDirection(Coordinates c,float azimuth, float inclination, int lengthUnits, int maxDist){
		
			//Calculate distance
			calculateDistance(c, lengthUnits);
			
			angle = c.getAngleToCam(coord, azimuth + 90);
			toDisplay = azimuth;
			toDisplay2 = angle;
			//If the interest point is between 0 and 40 degrees, then draw on the display
			if(maxDist != 0){
				if(angle > 0 && angle < 30 && distance < maxDist && distance > 0.1){
					inScreen =  true;
					
					p.x = Math.round(width - Math.abs(angle-30)*width/30);
					if(id == 12){
						Log.i("inscreen","in screen = " + Boolean.toString(inScreen));
					}
					p.y = Math.round((height-80)- (Math.round(distance*(height-80)/maxDist)));
				} 
				else{
					inScreen = false;
				}
			} else if(maxDist == 0){
				if(angle > 0 && angle < 30){
					inScreen =  true;
					
					p.x = Math.round(width - Math.abs(angle-30)*width/30);
					if(id == 12){
						Log.i("inscreen","in screen = " + Boolean.toString(inScreen));
					}
					//p.y = Math.round((height-80)- (Math.round(distance*(height-80)/maxDist)));
					p.y = Math.round(height/2);
				} 
				else{
					inScreen = false;
				}
			}
			//Call the onDraw method which repaint the POI button.
			invalidate();
		}
	
	/**
	 * Calculate the distance between the point of interest and the current position.
	 * @param c Coordinates of the current position
	 * @param lenghtUnits The units to show the distance with
	 */
	public void calculateDistance(Coordinates c,int lenghtUnits){
		//Calculate the distance 
		switch (lenghtUnits) {
		
			//The length unit is m/kilometer
			case 0:
				distance = c.getDistance_km(coord);
				unit = "km";
				break;
			
			//The length unit is feet/mile
			case 1:
				distance = c.getDistance_mile(coord);
				unit = "mile";
				break;
				
			//The length unit is yard
			case 2:
				distance = c.getDistance_yard(coord);
				unit = "yard";
				break;
			}
	}
	
	/**
	 * Draws the point of interest.
	 * @param posx The position where the point will be drawn
	 */
	public void drawOn(float posx){
		p.x = Math.round(posx);
		inScreen = true;
	}
	
	public boolean isClicked(Point touch){
		if(inScreen){
			return ((p.x <= touch.x)&&(touch.x <= (p.x+background.getWidth())))&& 
				((p.y <= touch.y)&&(touch.y <= (p.y+background.getHeight())));
		} else{
			return false;
		}
	}

	@Override
	public int getId() {
		return id;
	}

	@Override
	public void setId(int id) {
		this.id = id;
	}

	public Coordinates getCoord() {
		return coord;
	}

	public void setCoord(Coordinates coord) {
		this.coord = coord;
	}

	public Bitmap getImage() {
		return image;
	}

	public void setImage(Bitmap image) {
		this.image = image;
	}

	public float getDistance() {
		return distance;
	}

	public void setDistance(float distance) {
		this.distance = distance;
	}
	
	public float getLastAzimuth(){
		return oldAzimuth;
	}
	
	public void setLastAzimuth(float az){
		oldAzimuth = az;
	}
}